package com.thp.bigdata.webLog;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.junit.Test;

public class DemoTest {

	
	
	
		
	
	// static List<String> sessionIds = new ArrayList<String>();
	// static Set<String> sessionIds  = new HashSet<String>();
	
	static BufferedWriter bw;
	
	public static void main(String[] args) throws IOException {
		
		bw =  new BufferedWriter(new FileWriter("out.txt"));
		
		// 得到ip对应的SessionBean 的List集合
		Map<String, List<SessionBean>> IPListMap = getIPSessionBeanMap();
		
		
		// Set<Entry<String, List<SessionBean>>> entrySet = map.entrySet();
		
		
		/*for(Entry<String, List<SessionBean>> entrySet : IPListMap.entrySet()) {
			System.out.println("ip : " + entrySet.getKey() + " -- " + entrySet.getValue().size());
			
		}*/
		
		// 对IPListMap每一个键值对数据里面的List的SessionBean按照时间进行排序
		sortByDate(IPListMap);
		// 生成sessionId
		makeSessionId(IPListMap);
		
		
		for(Entry<String, List<SessionBean>> entrySet : IPListMap.entrySet()) {
			System.out.println("ip : " + entrySet.getKey() + " -- " + entrySet.getValue());
			
			// bw.write("ip : " + entrySet.getKey() + " -- " + entrySet.getValue() + "\n");
		}
		
		
		
		
		Map<String, List<SessionBean>> sessionIdListMap = new HashMap<String, List<SessionBean>>();
		
		for(Entry<String, List<SessionBean>> entrySet : IPListMap.entrySet()) {
			List<SessionBean> sessionBeans = entrySet.getValue();
			for(SessionBean sessionBean : sessionBeans) {
				// 千万要注意这些Map的区别含义，别搞混了，搞混了，那么清洗出来的数据都是错的   注意获取的是sessionId 而不是 IP  如果是IP 的话，那么会
				// 一直只有一条数据
				List<SessionBean> list = sessionIdListMap.get(sessionBean.getSessionId());
// System.out.println("((((((((((((((((((((((((");
// System.out.println(list);
				if(list == null) {
					list = new ArrayList<SessionBean>();
				}
				list.add(sessionBean);
				// 此时的key 变成sessionID了
				sessionIdListMap.put(sessionBean.getSessionId(), list);
// System.out.println("[[[[[[[[[[[[[[[[[");
// System.out.println(list);
// System.out.println("[[[[[[[[[[[[[[[[[");
			}
		}
		
		
System.out.println("++++++++++++++++++++++++++++");
		
		for(Entry<String, List<SessionBean>> entrySet : sessionIdListMap.entrySet()) {
			String sessionId = entrySet.getKey();
			List<SessionBean> sessionBeans = entrySet.getValue();
// System.out.println(sessionBeans.size());
			SessionBean start = sessionBeans.get(0);
// System.out.println("start :" + start);
			SessionBean end = sessionBeans.get(sessionBeans.size() - 1);
// System.out.println("end : " + end);
			long differ = end.getDate().getTime() - start.getDate().getTime();
			
			String res = sessionId + "\t" + start.getIp() + "\t" + start.getDate() + "\t" + end.getDate() +
					"\t" + start.getUrl() + "\t" + end.getUrl() + "\t" + (differ/1000);
			System.out.println(res);
			// bw.write(res + "\n");
			// bw.write(sessionId + "\n");
			
		}
		
		
		
		
		
		
		// bw.write("++++++++++++++++++++++++++++++");
		
		 
		 
		/* for(String sessionId : sessionIds) {
			 // System.out.println(sessionId);
			 
		 }*/
		 
		 // bw.write(sessionIds.size());
		 /*for(String sessionId : sessionIds) {
			 List<SessionBean> list = sessionIdListMap.get(sessionIds);
			 System.out.println(list);
			 bw.write(list.toString() + "\n");
		 }*/
// bw.write("------------------------------------------\n");
		 
		 
		 
// System.out.println("++++++++++++++++++++++++++++++++++++++++");
// System.out.println(sessionIds.size());
		 // System.out.println(sessionIds.);
// System.out.println("++++++++++++++++++++++++++++++++++++++++");
		 
		 
// System.out.println(sessionIdListMap.size()); 
		
		bw.close();
		
		
		/*System.out.println("-----------------------------");
		System.out.println("-----------------------------");
		System.out.println("-----------------------------");
		System.out.println("-----------------------------");
		System.out.println("-----------------------------");*/
		
		
		/*for(String sessionId : sessionIds) {
			List<SessionBean> list = sessionIdListMap.get(sessionId);
			// System.out.println(list.size());
		}*/
		
		
		
		
		
		
		
		
	}
	
	
	/**
	 * 对List里面的SessionBean 按照时间排序之后，生成SessionId
	 * @param IPListSortedMap
	 */
	private static void makeSessionId(Map<String, List<SessionBean>> IPListSortedMap) {
		for(Entry<String, List<SessionBean>> entrySet : IPListSortedMap.entrySet()) {
			List<SessionBean> sessionBeans = entrySet.getValue();
			if(sessionBeans.size() == 1) {  // 长度等于1时
				SessionBean sessionBean = sessionBeans.get(0);
				sessionBean.setSessionId(getSessionId(sessionBean.getIp()));
				sessionBean.setOrder(1);
			}
			// 当长度大于1时
			for(int i = 0; i < sessionBeans.size() - 1; i++) {
				SessionBean sb1 = sessionBeans.get(i);
				SessionBean sb2 = sessionBeans.get(i+1);
				// 同一个session的时候
				if(isSameSession(sb1, sb2)) {
					// 早的那个可能之前就已经设置了sessionId  就是上面的步骤设置了  那么order也一同设置了
					if(sb1.getSessionId() != null) {
						// System.out.println("----------------------------------");
						sb2.setSessionId(sb1.getSessionId());
						sb2.setOrder(sb1.getOrder() + 1);
// System.out.println("------------------");
// System.out.println(sb1.getSessionId());
// System.out.println("------------------");
// sessionIds.add(sb1.getSessionId());
					} else {
						sb1.setSessionId(getSessionId(sb1.getIp()));
						sb1.setOrder(1);
// sessionIds.add(sb1.getSessionId());
						sb2.setSessionId(sb1.getSessionId());
						sb2.setOrder(sb1.getOrder() + 1);
					}
				} else {
					// 不是同一个session
					if(sb1.getSessionId() != null) {
						sb2.setSessionId(getSessionId(sb2.getIp()));
						sb2.setOrder(1); // sb2是来自新的一个session, order要设置为1
					} else {
						sb1.setSessionId(getSessionId(sb1.getIp()));
						sb1.setOrder(1);
						sb2.setSessionId(getSessionId(sb2.getIp()));
						sb2.setOrder(1);
					}
				}
				
				
			}
		}
	}
	
	/**
	 * 根据SessionBean 的时间判断是不是同一个session
	 * @param s1
	 * @param s2
	 * @return
	 */
	private static boolean isSameSession(SessionBean s1, SessionBean s2) {
		long time1 = s1.getDate().getTime();
		long time2 = s2.getDate().getTime();
		// session 时间 0 - 30 分钟
		long differ = time2 - time1;
		if(differ >=0 && differ <= (1000*60*30)) {
			return true;
		}
		return false;
	}
	
	
	
	
	/**
	 * 生成sessionId的方法
	 */
	private static String getSessionId(String ip) {
		// Integer.parseInt(ip);
		String[] fields = ip.split("\\.");
		StringBuffer sb = new StringBuffer();
		for(String field : fields) {
			sb.append(field);
		}
		long longIP = Long.parseLong(sb.toString());
		long nanoTime = System.nanoTime();
		return ""+longIP+nanoTime;
	}
	
	
	
	@Test
	public void testIPtoLong() {
		String ip = "194.237.142.21";
		String[] fields = ip.split("\\.");
		// ip.split(".");
// System.out.println(Arrays.toString(fields));
		StringBuffer sb = new StringBuffer();
		for(String field : fields) {
// System.out.println(field);
			sb.append(field);
		}
// System.out.println(sb.toString());
		long parseLong = Long.parseLong(sb.toString());
// System.out.println("" +parseLong + 2L);
	}
	
	@Test
	public void testNanoTime() {
		
		System.out.println(System.nanoTime() + "");
	}
	
	
	
	/**
	 * 对IPListMap里的每一条数据的List中的SessionBean按照时间进行排序
	 * @param IPListMap
	 */
	private static void sortByDate(Map<String, List<SessionBean>> IPListMap) {
		for(Entry<String, List<SessionBean>> entrySet : IPListMap.entrySet()) {
			List<SessionBean> list = entrySet.getValue();
			Collections.sort(list, new Comparator<SessionBean>() {
				@Override
				public int compare(SessionBean o1, SessionBean o2) {
					Date date1 = o1.getDate();
					Date date2 = o2.getDate();
					return date1.before(o2.getDate()) ? -1 : 1;
				}
				
			});
		}
	}
	
	
	
	
	private static Map<String, List<SessionBean>> getIPSessionBeanMap() {
		Map<String, List<SessionBean>> map1 = new HashMap<String,List<SessionBean>> ();
		
		
		
		
		BufferedReader bufferedReader = null;
		try {
			// bufferedReader = new BufferedReader(new FileReader(DemoTest.class.getResource("access.log.fensi").getPath()));
			bufferedReader = new BufferedReader(new FileReader(DemoTest.class.getResource("data.dat").getPath()));
			
			// System.out.println(DemoTest.class.getResource("access.log.fensi").getPath());
			
			// System.out.println(bufferedReader.readLine());
			
			
			String line = null;
			while((line = bufferedReader.readLine()) != null) {
				// 数字 + .  (连续出现三次)  + 最后一次出现的还是数字   -- \\d+ 代表的是多个数字
				String ipRegex = "(\\d+\\.){3}\\d+";
				// [ + 任何单字符 + 数字(一个或者多个) + ]
				String dateRegex ="\\[.+\\d+\\]";
				//  首先是 GET 或者 POST (只要有一个出现就可以匹配)  + 空格 + 非空格的字符(0次或者多次)
				String urlRegex = "(POST|GET){1}\\s(\\S)*\\s";
				
				String ip = getConByRegex(line, ipRegex);
				String date = getConByRegex(line, dateRegex);
				String url  =getConByRegex(line, urlRegex);
				
				
				
// System.out.println(ip + " -- " + date + " -- " + url);
				if(ip != null && date != null && url != null) {
					SessionBean sessionBean = new SessionBean();
					sessionBean.setIp(ip);
					sessionBean.setDate(parDateFromStr(date));
					sessionBean.setUrl(url);
					List<SessionBean> list = map1.get(ip);
					if(list == null) {
						list = new ArrayList<SessionBean>();
					}
					list.add(sessionBean);
					map1.put(ip, list);
				}
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if(bufferedReader != null) {
				try {
					bufferedReader.close();
				} catch (IOException e) {
					e.printStackTrace();
				} finally {
					bufferedReader = null;
				}
			}
		}
		
		return map1;
	}
	
	
	
	/**
	 * 将日期格式的字符串转换为Date类型
	 * @param dataStr
	 * @return
	 */
	private static Date parDateFromStr(String dateStr) {
		// [19/Sep/2013:04:38:11 +0000]
		String substring = dateStr.substring(1, dateStr.length() - 1);
// System.out.println(substring);
		// 注意是有 三个 M ， 后面要加上Locale.US  否则会报错
		SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MMM/yyyy:HH:mm:ss",Locale.US);
		try {
			return dateFormat.parse(substring);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		System.err.println("< 日期解析异常 >");
		return null;
	}
	
	
	
	@Test
	public void testParseDate() {
		String dateStr = "18/Sep/2013:06:49:18 +0000";
		SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MMM/yyyy:HH:mm:ss",Locale.US);
		try {
			Date date = dateFormat.parse(dateStr);
			return;
		} catch (ParseException e) {
			e.printStackTrace();
		}
		System.err.println("< 日期解析异常 >");
		
		
	}

	
	
	
	/**
	 * 匹配字符串
	 * @param line
	 * @param regex
	 * @return
	 */
	private static String getConByRegex(String line, String regex) {
		Pattern compile = Pattern.compile(regex);
		Matcher matcher = compile.matcher(line);
		while(matcher.find()) {
			// 返回的是符合正则规则的字符串
			return matcher.group();
		}
		return null;
	}
	
	
	
	
	
	@Test
	public void testRegex() {
		
		String line = "GETGETPOST /wp-content/uploads/2013/07/rstudio-git3.png HTTP/1.1";
		
		// String ipRegex = "(\\d+\\.){3}\\d+";
		// String regex ="\\[.+\\d+\\]";
		String regex = "(POST|GET){1}\\s(\\S)*\\s";
		
		
		Pattern compile = Pattern.compile(regex);
		
		Matcher matcher = compile.matcher(line);
		
		while(matcher.find()) {
			System.out.println(matcher.group());
			return;
		}
		
		System.out.println("没有匹配");
		
		return;
	}
	
	@Test
	public void testLineData() {
		String lineData = "194.237.142.21 - - [18/Sep/2013:06:49:18 +0000] \"GET /wp-content/uploads/2013/07/rstudio-git3.png HTTP/1.1\" 304 0 \"-\" \"Mozilla/4.0 (compatible;)\"";
		String[] fields = lineData.split(" ");
		for(String field : fields) {
			System.out.println(field);
		}
		
	}
	
}
